/*
 * Created by JFormDesigner on Wed Jun 12 11:26:48 CST 2024
 */

package com.vict.gui;

import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.*;
import java.io.File;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
import javax.swing.*;

import cn.hutool.core.io.FileUtil;
import com.vict.GuiApplication;
import com.vict.bean.FileDto;
import com.vict.service.MusicService;
import com.vict.util.FileUtils;
import com.vict.util.IdUtils;
import com.vict.util.LockJdk;
import com.vict.util.ObjectUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

/**
 * @author Brainrain
 */
@Slf4j
public class MainWIndowGui extends JFrame {
    static SystemTray tray = SystemTray.getSystemTray();

    private DefaultListModel<String> listModel;


    public MainWIndowGui() {
        initComponents();

        listModel = new DefaultListModel<String>();

        JList fileList = getList();
        fileList.setModel(listModel);

        fileList.setTransferHandler(new ListTransferHandler());

        reloadAllDrive();
    }

    /** 重载U盘 */
    private void reloadAllDrive(){
        // this.allDrive.removeAll();
        this.allDrive.removeAllItems(); // 移除全部
        List<File> allUsbDrive = FileUtils.searchAllUsbDrive(); // 寻找全部U盘
        for(File drive : allUsbDrive){
            String absolutePath = drive.getAbsolutePath();
            this.allDrive.addItem(absolutePath);
        }
        this.allDrive.setSelectedIndex(allUsbDrive.size() - 1);
    }

    private void fixAllFileIndex(){
        for(int i = 0; i < this.listModel.size() ; i++){
            String allItemStr = this.listModel.get(i);
            int splitIndex = allItemStr.indexOf(" ");
            String split = allItemStr.substring(splitIndex + 1);
            this.listModel.set(i, (i + 1) + ". " + split);
        }
    }

    private class ListTransferHandler extends TransferHandler {
        private int removeIndex;
        private String removeData;
        private int addIndex;
        private String addData;
        @Override
        public int getSourceActions(JComponent c) {
            return MOVE;
        }

        @Override
        protected Transferable createTransferable(JComponent c) {
            this.removeIndex = list.getSelectedIndex();
            return new StringSelection(list.getSelectedValue().toString());
        }

        @Override
        protected void exportDone(JComponent source, Transferable data, int action) {
            if(action == MOVE){
                log.info("后移除 selectIndex:{}, addIndex: {}, 移除data: {}, ", this.removeIndex, this.addIndex, listModel.get(this.removeIndex));
                if(this.addIndex < this.removeIndex){
                    this.removeIndex++;
                }
                String removeData = listModel.remove(removeIndex);
                this.removeData = removeData;
                fixAllFileIndex();
            }
        }

        @Override
        public boolean canImport(TransferSupport support) {
            return support.isDataFlavorSupported(DataFlavor.stringFlavor);
        }

        @Override
        public boolean importData(TransferSupport support) {
            try{
                String data = (String) support.getTransferable().getTransferData(DataFlavor.stringFlavor);
                JList.DropLocation dropLocation = (JList.DropLocation)support.getDropLocation();
                this.addIndex = dropLocation.getIndex();
                this.addData = data;
                listModel.add(this.addIndex, data);
                log.info("先添加 selectIndex: {}, addIndex: {}, 添加data : {}", this.removeIndex, this.addIndex, data);
                return true;
            }catch(Exception e){
                e.printStackTrace();
            }
            return false;
        }
    }

    private void refreshAction(ActionEvent e) {
        reloadAllDrive();
    }

    public static Map<String, FileDto> fileDtoMap;

    /** 选中之后加载全部, 歌曲*/
    private void allDriveSelect(ActionEvent e) {
        if(listModel == null){
            return;
        }
        listModel.clear();
        Object selectedItem = this.allDrive.getSelectedItem();
        if(selectedItem == null){
            return;
        }
        // 加载全部mp3文件
        // TODO
        List<File> allSubFileOrderByCreateTime = FileUtils.getAllSubFileOrderByCreateTime(new File(selectedItem.toString()), "mp3");
        // List<File> allSubFileOrderByCreateTime = FileUtils.getAllSubFileOrderByCreateTime(new File("D:\\音乐\\test3"), "mp3");
        allSubFileOrderByCreateTime = Optional.ofNullable(allSubFileOrderByCreateTime).orElse(new ArrayList<>());

        List<FileDto> fileDtos = MusicService.loadAllFile(allSubFileOrderByCreateTime);
        fileDtoMap = fileDtos.stream().collect(Collectors.toMap(o -> o.getId(), o -> o));

        for(int i = 0 ; i < fileDtos.size() ;i++){
            FileDto fileDto = fileDtos.get(i);
            listModel.addElement((i + 1) + ". " + fileDto.getShowFileName() + "." + fileDto.getId());
        }
    }

    private void menuItemLog(ActionEvent e) {
        Optional.ofNullable(GuiApplication.guiApplication)
                .map(o-> o.getLogGui())
                .ifPresent(o-> o.setVisible(true));
    }

    public JList getList(){
        return this.list;
    }

    public JComboBox getAllDrive() {
        return allDrive;
    }

    /**
     * 保存
     */
    @SneakyThrows
    private void saveBtnAction(ActionEvent e) {
        LockJdk lock = LockJdk.getLockOverThrowException("save", 10L * 60L);
        boolean b = lock.lockNotBlock();
        if(b){
            try{
                long time = System.currentTimeMillis() - 4L * 24L * 60L * 60L * 1000L;

                String str0 = listModel.get(0);
                String id0 = str0.substring(str0.lastIndexOf(".") + 1, str0.length());
                FileDto fileDto0 = fileDtoMap.get(id0);
                // 获取本文件夹
                String dirPath = fileDto0.getRealFile().getParentFile().getAbsolutePath();
                // 获取临时文件夹
                String tempDir = IdUtils.getSalt(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray());
                String tempDirPath = fileDto0.getRealFile().getParentFile().getAbsolutePath() + "\\" + tempDir;
                // 创建临时文件夹
                FileUtil.mkdir(tempDirPath);
                File tempFile = new File(tempDirPath);

                Object selectedItem = this.allDrive.getSelectedItem();
                if(selectedItem == null){
                    return;
                }
                // 加载全部文件
                // TODO
                List<File> allFile = FileUtils.getAllSubFileOrderByCreateTime(new File(selectedItem.toString()));
                List<File> allMp3File = FileUtils.getAllSubFileOrderByCreateTime(new File(selectedItem.toString()), "mp3");
                // List<File> allFile = FileUtils.getAllSubFileOrderByCreateTime(new File("D:\\音乐\\test3"));
                // List<File> allMp3File = FileUtils.getAllSubFileOrderByCreateTime(new File("D:\\音乐\\test3"), "mp3");

                // 全部mp3文件移动到temp文件夹
                for(int i = 0 ; i < listModel.size() ; i++){
                    String str = listModel.get(i);

                    int splitIndex = str.indexOf(" ");
                    str = str.substring(splitIndex + 1);

                    String id = str.substring(str.lastIndexOf(".") + 1, str.length());
                    FileDto fileDto = fileDtoMap.get(id);

                    long fileTime = time + 60L * 1000L * i;

                    // 重命名当前文件
                    File renameFile = MusicService.rename(fileDto.getRealFile(), i + 1);
                    if(renameFile == null){
                        continue;
                    }
                    fileDto.setRealFile(renameFile);
                    // 更新当前文件时间
                    FileUtils.updateFileTime(fileDto.getRealFile(), fileTime);

                    // 移动到temp文件夹
                    File targetFile = new File(tempDirPath, fileDto.getRealFile().getName());
                    FileUtils.move(fileDto.getRealFile(), targetFile);
                    fileDto.setRealFile(targetFile);
                    // FileUtils.move();
                }

                List<File> otherFileList = new ArrayList<>();
                Collection<FileDto> mp3Files = fileDtoMap.values();
                for(File file : allFile){
                    if(allMp3File.contains(file)){
                        continue;
                    }
                    if(file.equals(tempFile)){
                        continue;
                    }
                    FileUtils.updateFileTime(file, System.currentTimeMillis() - 3L * 24L * 60L * 60L * 1000L);
                    // 移动到temp文件夹
                    File targetFile = new File(tempDirPath, file.getName());
                    FileUtils.move(file, targetFile);
                    otherFileList.add(targetFile);
                }

                for(int i = 0 ; i < listModel.size() ; i++){
                    String str = listModel.get(i);

                    int splitIndex = str.indexOf(" ");
                    str = str.substring(splitIndex + 1);

                    String id = str.substring(str.lastIndexOf(".") + 1, str.length());
                    FileDto fileDto = fileDtoMap.get(id);

                    // 移动到dir文件夹
                    File targetFile = new File(dirPath, fileDto.getRealFile().getName());
                    FileUtils.move(fileDto.getRealFile(), targetFile);
                    fileDto.setRealFile(targetFile);
                }

                for(File file : otherFileList){
                    // 移动到dir文件夹
                    File targetFile = new File(dirPath, file.getName());
                    FileUtils.move(file, targetFile);
                }

                // 删除临时文件夹
                tempFile.delete();
            }finally {
                lock.unlockIfSuccess();
            }
        }
    }

    private void execNum(ActionEvent e) {
        Integer integer = Optional.ofNullable(this.textFieldExecNum.getText()).map(o -> o.trim()).filter(o -> !o.equals(""))
                .map(o -> Integer.parseInt(o)).orElse(null);
        if(integer == null){
            return;
        }
        if(integer <= 0){
            textFieldExecNum.setText("");
            return;
        }
        if(integer > listModel.size()){
            textFieldExecNum.setText("");
            return;
        }
        int selectedIndex = list.getSelectedIndex();
        if(selectedIndex < 0){
            return;
        }
        String removeData = listModel.remove(selectedIndex);
        // Object selectedValue = this.list.getSelectedValue();
        listModel.add(integer - 1, removeData);
        fixAllFileIndex();

        textFieldExecNum.setText("");
    }



    private void initComponents() {
        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents
        menuBar1 = new JMenuBar();
        menu2 = new JMenu();
        menuItem3 = new JMenuItem();
        scrollPane1 = new JScrollPane();
        list = new JList();
        allDrive = new JComboBox();
        button1 = new JButton();
        refresh = new JButton();
        label1 = new JLabel();
        label2 = new JLabel();
        buttonExecNum = new JButton();
        textFieldExecNum = new JTextField();
        label3 = new JLabel();

        //======== this ========
        setIconImage(new ImageIcon(getClass().getResource("/icon.png")).getImage());
        setResizable(false);
        var contentPane = getContentPane();
        contentPane.setLayout(null);

        //======== menuBar1 ========
        {

            //======== menu2 ========
            {
                menu2.setText("\u7cfb\u7edf");

                //---- menuItem3 ----
                menuItem3.setText("\u65e5\u5fd7");
                menuItem3.addActionListener(e -> menuItemLog(e));
                menu2.add(menuItem3);
            }
            menuBar1.add(menu2);
        }
        setJMenuBar(menuBar1);

        //======== scrollPane1 ========
        {

            //---- list ----
            list.setDragEnabled(true);
            list.setDropMode(DropMode.INSERT);
            list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
            scrollPane1.setViewportView(list);
        }
        contentPane.add(scrollPane1);
        scrollPane1.setBounds(20, 55, 725, 445);

        //---- allDrive ----
        allDrive.addActionListener(e -> allDriveSelect(e));
        contentPane.add(allDrive);
        allDrive.setBounds(20, 15, 185, allDrive.getPreferredSize().height);

        //---- button1 ----
        button1.setText("\u4fdd\u5b58");
        button1.addActionListener(e -> saveBtnAction(e));
        contentPane.add(button1);
        button1.setBounds(new Rectangle(new Point(665, 15), button1.getPreferredSize()));

        //---- refresh ----
        refresh.setText("\u5237\u65b0");
        refresh.addActionListener(e -> refreshAction(e));
        contentPane.add(refresh);
        refresh.setBounds(new Rectangle(new Point(240, 15), refresh.getPreferredSize()));

        //---- label1 ----
        label1.setText("\u6ca1\u6709\u6570\u636e\u9700\u5237\u65b0");
        label1.setForeground(new Color(255, 0, 51));
        contentPane.add(label1);
        label1.setBounds(new Rectangle(new Point(335, 20), label1.getPreferredSize()));

        //---- label2 ----
        label2.setText("\u4fdd\u5b58\u751f\u6548:");
        label2.setForeground(new Color(255, 0, 51));
        contentPane.add(label2);
        label2.setBounds(new Rectangle(new Point(600, 20), label2.getPreferredSize()));

        //---- buttonExecNum ----
        buttonExecNum.setText("\u6267\u884c");
        buttonExecNum.addActionListener(e -> execNum(e));
        contentPane.add(buttonExecNum);
        buttonExecNum.setBounds(225, 515, 90, buttonExecNum.getPreferredSize().height);
        contentPane.add(textFieldExecNum);
        textFieldExecNum.setBounds(105, 520, 70, 20);

        //---- label3 ----
        label3.setText("\u79fb\u52a8\u6587\u4ef6\u5230");
        contentPane.add(label3);
        label3.setBounds(25, 520, 80, 20);

        {
            // compute preferred size
            Dimension preferredSize = new Dimension();
            for(int i = 0; i < contentPane.getComponentCount(); i++) {
                Rectangle bounds = contentPane.getComponent(i).getBounds();
                preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width);
                preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height);
            }
            Insets insets = contentPane.getInsets();
            preferredSize.width += insets.right;
            preferredSize.height += insets.bottom;
            contentPane.setMinimumSize(preferredSize);
            contentPane.setPreferredSize(preferredSize);
        }
        setSize(770, 615);
        setLocationRelativeTo(getOwner());
        // JFormDesigner - End of component initialization  //GEN-END:initComponents
    }

    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables
    private JMenuBar menuBar1;
    private JMenu menu2;
    private JMenuItem menuItem3;
    private JScrollPane scrollPane1;
    private JList list;
    private JComboBox allDrive;
    private JButton button1;
    private JButton refresh;
    private JLabel label1;
    private JLabel label2;
    private JButton buttonExecNum;
    private JTextField textFieldExecNum;
    private JLabel label3;
    // JFormDesigner - End of variables declaration  //GEN-END:variables
}
